package org.flashamaphone.voices
{
	import flash.utils.ByteArray;
	import org.flashamaphone.voices.waveformFactories.IWaveFactory;
	import org.flashamaphone.buffer.SoundConstants;
	
	public class ADSRWaveform extends SimpleWaveform
	{
		/** attack waveform factory */
		public var attackWaveform:IWaveFactory;
		
		/** decay waveform factory */
		public var decayWaveform:IWaveFactory;
		
		/** sustain waveform factory */
		public var sustainWaveform:IWaveFactory;
		
		/** release waveform factory */
		public var releaseWaveform:IWaveFactory;
		
		public function ADSRWaveform(attackWaveform:IWaveFactory=null, decayWaveform:IWaveFactory=null, sustainWaveform:IWaveFactory=null, releaseWaveform:IWaveFactory=null )
		{
			if (attackWaveform) {
				this.attackWaveform = attackWaveform;
			}
			
			if (decayWaveform) {
				this.decayWaveform = decayWaveform;
			}
			
			if (sustainWaveform) {
				this.sustainWaveform = sustainWaveform;
			}
			
			if (releaseWaveform) {
				this.releaseWaveform = releaseWaveform;
			}
			
			super(attackWaveform);
		}
		
		/**
		 * get attack bytes
		 * 
		 * @param frequency
		 * @param duration (milliseconds)
		 * @return sound byteArray
		 */
		public override function attack(freq:Number, milliseconds:Number):ByteArray {
			var returnBytes:ByteArray = new ByteArray();
			var numSamples:int = (milliseconds * SoundConstants.SAMPLING_RATE_MILLISECONDS);
			
			if (attackWaveform) {
				returnBytes = attackWaveform.cycle(freq, numSamples, attackWaveform.lastSampleIndex);
			} else {
				returnBytes = wave.cycle(freq, numSamples, wave.lastSampleIndex);
			}
			return returnBytes;
		}
		
		/**
		 * get decay bytes
		 * 
		 * @param frequency
		 * @param duration (milliseconds)
		 * @return sound byteArray
		 */
		public override function decay(freq:Number, milliseconds:Number):ByteArray {
			var returnBytes:ByteArray = new ByteArray();
			var numSamples:int = (milliseconds * SoundConstants.SAMPLING_RATE_MILLISECONDS);
			if (decayWaveform) {
				returnBytes = decayWaveform.cycle(freq, numSamples, decayWaveform.lastSampleIndex);
			} else {
				returnBytes = wave.cycle(freq, numSamples, wave.lastSampleIndex);
			}
			return returnBytes;
		}
		
		/**
		 * get sustain bytes
		 * 
		 * @param frequency
		 * @param duration (milliseconds)
		 * @return sound byteArray
		 */
		public override function sustain(freq:Number, milliseconds:Number):ByteArray {
			var returnBytes:ByteArray = new ByteArray();
			var numSamples:int = (milliseconds * SoundConstants.SAMPLING_RATE_MILLISECONDS);
			if (sustainWaveform) {
				returnBytes = sustainWaveform.cycle(freq, numSamples, sustainWaveform.lastSampleIndex);
			} else {
				returnBytes = wave.cycle(freq, numSamples, wave.lastSampleIndex);
			}
			return returnBytes;
		}
		
		/**
		 * get release bytes
		 * 
		 * @param frequency
		 * @param duration (milliseconds)
		 * @return sound byteArray
		 */
		public override function release(freq:Number, milliseconds:Number):ByteArray {
			var returnBytes:ByteArray = new ByteArray();
			var numSamples:int = (milliseconds * SoundConstants.SAMPLING_RATE_MILLISECONDS);
			if (releaseWaveform) {
				returnBytes = releaseWaveform.cycle(freq, numSamples, releaseWaveform.lastSampleIndex);
			} else {
				returnBytes = wave.cycle(freq, numSamples, wave.lastSampleIndex);
			}
			return returnBytes;
		}

	}
}